<?php


namespace app\common\tools;


use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use think\facade\Db;

class AliyunSms
{
    use Instance;

    const SUCCESS_CODE = "OK";
    const SIGN_NAME = "猪好多科技";

    const TEMPLATE_CODE = [
        'AUTHENTICATION' => 'SMS_179875253', // 身份验证验证码
        'LOGIN_VERIFICATION' => 'SMS_179875252', // 登录确认验证码
        'LOGIN_EXCEPTION' => 'SMS_179875251', // 登录异常验证码
        'USER_REGISTRATION' => 'SMS_179875250', // 用户注册验证码
        'CHANGE_PASSWORD' => 'SMS_179875249', // 修改密码验证码
        'INFORMATION_CHANGE' => 'SMS_179875248', // 信息变更验证码
    ];

    const TEMPLATE_TEXT = [
        'AUTHENTICATION' => '验证码${code}，您正在进行身份验证，打死不要告诉别人哦！',
        'LOGIN_VERIFICATION' => '验证码${code}，您正在登录，若非本人操作，请勿泄露。',
        'LOGIN_EXCEPTION' => '验证码${code}，您正尝试异地登录，若非本人操作，请勿泄露。',
        'USER_REGISTRATION' => '验证码${code}，您正在注册成为新用户，感谢您的支持！',
        'CHANGE_PASSWORD' => '验证码${code}，您正在尝试修改登录密码，请妥善保管账户信息。',
        'INFORMATION_CHANGE' => '验证码${code}，您正在尝试变更重要信息，请妥善保管账户信息。',
    ];

    /**
     * AliyunSms constructor.
     * @param $accessKeyId
     * @param $accessKeySecret
     * @param string $regionId
     * @throws
     * @author 刘宏盟
     */
    public function __construct($accessKeyId = 'LTAI4FehPBFjQ9D8hPZ2sq8Z'
        , $accessKeySecret = 'rDA1w20b9o3rUQBnD0JuexLTYzRbMF', $regionId = 'cn-hangzhou')
    {
        AlibabaCloud::accessKeyClient($accessKeyId, $accessKeySecret)
            ->regionId($regionId)
            ->asDefaultClient();
    }


    /**
     * 尝试修改密码
     * @param $phoneNumbers
     * @param null $paramCode
     * @return array
     * @author 刘宏盟
     */
    public function changePassword($phoneNumbers, $paramCode = null)
    {
        $code = self::TEMPLATE_CODE['CHANGE_PASSWORD'];
        $param = ['code' => $paramCode ?? mt_rand(10000, 99999)];
        if (null === ($resAliyun = $this->sendSms($phoneNumbers, $code, $param))) {
            return [false, $resAliyun['Message']];
        }
        $this->recordDataBase($phoneNumbers, $param, $resAliyun, self::TEMPLATE_TEXT['CHANGE_PASSWORD'], $param['code']);
        return [$resAliyun['Code'] === self::SUCCESS_CODE, $resAliyun['Message']];
    }


    /**
     * @param $phone
     * @param int $code
     * @return array
     * @author 刘宏盟
     */
    public function authentication($phone, int $code)
    {
        $code = self::TEMPLATE_CODE['AUTHENTICATION'];
        $param = ['code' => $paramCode ?? mt_rand(10000, 99999)];
        if (null === ($resAliyun = $this->sendSms($phone, $code, $param))) {
            return [false, $resAliyun['Message']];
        }
        $this->recordDataBase($phone, $param, $resAliyun, self::TEMPLATE_TEXT['AUTHENTICATION'], $param['code']);
        return [$resAliyun['Code'] === self::SUCCESS_CODE, $resAliyun['Message']];
    }

    /**
     * 用户短信登陆
     * @param $phoneNumbers
     * @param null $paramCode
     * @return array
     * @author 刘宏盟
     */
    public function sendLogin($phoneNumbers, $paramCode = null)
    {
        $code = self::TEMPLATE_CODE['LOGIN_VERIFICATION'];
        $param = ['code' => $paramCode ?? mt_rand(10000, 99999)];
        if (null === ($resAliyun = $this->sendSms($phoneNumbers, $code, $param))) {
            return [false, $resAliyun['Message']];
        }

        $this->recordDataBase($phoneNumbers, $param, $resAliyun, self::TEMPLATE_TEXT['LOGIN_VERIFICATION'], $param['code']);
        return [$resAliyun['Code'] === self::SUCCESS_CODE, $resAliyun['Message']];
    }

    /**
     * 发送用户注册短信
     * @param $phoneNumbers
     * @param null $paramCode
     * @return array
     * @author 刘宏盟
     */
    public function sendUserRegistration($phoneNumbers, $paramCode = null)
    {
        $code = self::TEMPLATE_CODE['USER_REGISTRATION'];
        $param = ['code' => $paramCode ?? mt_rand(10000, 99999)];
        if (null === ($resAliyun = $this->sendSms($phoneNumbers, $code, $param))) {
            return [false, $resAliyun['Message']];
        }
        $this->recordDataBase($phoneNumbers, $param, $resAliyun, self::TEMPLATE_TEXT['USER_REGISTRATION'], $param['code']);
        return [$resAliyun['Code'] === self::SUCCESS_CODE, $resAliyun['Message']];
    }

    /**
     * @param $phoneNumbers
     * @param $templateCode
     * @param $templateParam
     * @param string $signName
     * @return array ["Message": "--","RequestId": "--","BizId": "--","Code": "OK"]
     * @author 刘宏盟
     */
    public function sendSms($phoneNumbers, $templateCode, $templateParam, $signName = self::SIGN_NAME)
    {
        // return ['Code'=>'OK','Message'=>'OK','RequestId'=>time()];
        try {
            $result = AlibabaCloud::rpc()
                ->product('Dysmsapi')
                ->version('2017-05-25')
                ->action('SendSms')
                ->method('POST')
                ->host('dysmsapi.aliyuncs.com')
                ->options([
                    'query' => [
                        'RegionId' => "cn-hangzhou",
                        'PhoneNumbers' => $phoneNumbers,
                        'SignName' => $signName,
                        'TemplateCode' => $templateCode,
                        'TemplateParam' => json_encode($templateParam),
                    ],
                ])
                ->request();
            return $result->toArray();
        } catch (ClientException | ServerException $e) {
            return null;
        }
    }

    /**
     * 记录到数据库
     * @param $phoneNumbers string 手机号码
     * @param $param array 发送数据参数
     * @param $resAliyun array 阿里云返回结果
     * @param $idCode string 验证码
     * @param $templateText
     * @param $userId
     * @author 刘宏盟
     */
    private function recordDataBase($phoneNumbers, $param, $resAliyun, $templateText, $idCode, $userId = 0)
    {
        $search = $replace = [];
        foreach ($param as $key => $val) {
            $search[] = '${' . $key . '}';
            $replace[] = $val;
        }
        $msg = str_replace($search, $replace, $templateText);

        $status = ($resAliyun['Code'] === self::SUCCESS_CODE ? '0' : '-1');
        $requestId = $resAliyun['RequestId'];
        // 记录到数据库
        Db::table('ea_sms_report')->insert([
            'mobile' => $phoneNumbers,
            'id_code' => $idCode,
            'msg' => $msg,
            'status' => $status,
            'send_userid' => $userId,
            'return_id' => $requestId,
            'posttime' => date('Y-m-d H:i:s'),
            'ip' => request()->ip(),
        ]);
    }
}
